﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CONEK911Manager.DAO;
using CONEK911Manager.DTO;

namespace CONEK911Manager.Service
{
    public class Calculate
    {
        private List<ProductDTO> _listProduct = new List<ProductDTO>();
        private List<AccountDTO> _listAccount = new List<AccountDTO>();
        private List<OrderDTO> _listOrder = new List<OrderDTO>();
        private List<OrderDetailDTO>  _listOrderDetail = new List<OrderDetailDTO>();
        private List<ActiveDTO> _listActive = new List<ActiveDTO>();
        private readonly AccountDAO _accountDao = new AccountDAO();
        private readonly ProductDAO _productDao = new ProductDAO();
        private readonly OrderDAO _orderDao = new OrderDAO();
        private readonly OrderDetailDAO _orderDetailDao = new OrderDetailDAO();
        private readonly ActiveDAO _activeDao = new ActiveDAO();
        private Dictionary<OrderDTO, double> _mapping  = new Dictionary<OrderDTO, double>();
        
        public void Initialize()
        {
            var breakPoint = DateTime.Now;
            _listAccount = _accountDao.GetAllAccount().ToList();
            _listProduct = _productDao.GetAllProduct().ToList();
            _listActive = _activeDao.GetAllActive().ToList();
            _listActive.Sort(delegate(ActiveDTO a1, ActiveDTO a2)
                {
                    if (a1.ActiveMoney < a2.ActiveMoney) return 1;
                    if (a1.ActiveMoney > a2.ActiveMoney) return -1;
                    return 0;
                });
            _listOrder = _orderDao.GetAllOrder().Where(i => i.OrderDate.Month == breakPoint.Month
                                                            & i.OrderDate.Year == breakPoint.Year).ToList();
            _listOrderDetail = _orderDetailDao.GetAllOrderDetail().ToList();
        }
        
        public void FindMoneyOfOrder()
        {
            foreach (var order in _listOrder)
            {
                double curr = 0.0;
                foreach (var detail in _listOrderDetail)
                {
                    if (detail.OrderID == order.OrderId)
                    {
                        double price = (from product in _listProduct where product.Code == detail.Code select product.Price).FirstOrDefault();
                        curr += price*detail.Quantity;
                    }
                }
                _mapping.Add(order, curr);
            }
        }
        private void SetActiveLevel()
        {
            foreach (var accountDTO in _listAccount)
            {
                double currentMoney = Math.Max(FindTotalMoney(accountDTO), FindLevel(accountDTO));
                foreach (var active in _listActive)
                {
                    if (currentMoney >= active.ActiveMoney)
                    {
                        accountDTO.ActiveId = accountDTO.ActiveId;
                        break;
                    }
                }
            }
            // _accountDao.SaveChange();
        }
        private double FindLevel(AccountDTO account )
        {
            return (from activeDTO in _listActive where account.ActiveId == activeDTO.ActiveID select activeDTO.ActiveMoney).FirstOrDefault();
        }
        public double FindTotalMoney(AccountDTO account)
        {
            var tmpOrder = _listOrder.Where(i => i.Account == account.Account);
            return tmpOrder.Sum(orderDTO => _mapping.Where(i => i.Key == orderDTO).Sum(i => i.Value));
        }
        public AccountDTO FindAnceesor(AccountDTO account)
        {
            return _listAccount.FirstOrDefault(accountDTO => accountDTO.Account == account.Ancessor);
        }
        public AccountDTO FindRoot()
        {
            return _listAccount.FirstOrDefault(accountDTO => accountDTO.Ancessor == "");
        }
        public List<AccountDTO> FindChildNode(AccountDTO account)
        {
            return _listAccount.Where(accountDTO => accountDTO.Ancessor == account.Account).ToList();
        }

        public double FindCommissions(AccountDTO account)
        {
            if (FindChildNode(account) == null || !FindChildNode(account).Any()) return 0;
			return 0;
        }
        public void Calculation()
        {
            Initialize();
            SetActiveLevel();
            FindCommissions(FindRoot());
        }
        
    }
}
